package com.derbysoft.dswitch.adapter.ihg.common.core.reflect;

import com.derbysoft.dswitch.adapter.ihg.common.utils.PackageUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.FactoryBean;

import java.util.ArrayList;
import java.util.List;

public class PackageClassCollector implements FactoryBean {

    private final Log logger = LogFactory.getLog(PackageClassCollector.class);


    private String scanPackages;

    /**
     * 需要扫描的包，使用,分隔的包名 eg:com.foo.bar;com.foo.bar2
     *
     * @param scanPackages comma-separated package names
     */
    public void setScanPackages(String scanPackages) {
        this.scanPackages = scanPackages;
    }


    private ClassFilter classFilter = ClassFilter.ETERNAL_MATCH_FILTER;


    /**
     * @param classFilter ClassFilter
     */
    public void setClassFilter(ClassFilter classFilter) {
        if (classFilter == null) {
            throw new IllegalArgumentException("can not set null ClassFilter");
        }
        this.classFilter = classFilter;
    }


    /**
     * create PackageClassCollector
     *
     * @param scanPackages comma-separated package name
     * @param classFilter  {@link ClassFilter}
     */
    public PackageClassCollector(String scanPackages, ClassFilter classFilter) {
        this.scanPackages = scanPackages;
        this.classFilter = classFilter;
    }


    public PackageClassCollector() {
        this(null, null);
    }


    /**
     * find class
     *
     * @return founded class
     */
    public List<Class<?>> findClasses() {
        List<Class<?>> matchedClasses = new ArrayList<Class<?>>();
        String[] packages = StringUtils.split(scanPackages, ",");
        for (String packageName : packages) {
            List<Class<?>> sublist = PackageUtils.getClasses(packageName);
            for (Class<?> currentClass : sublist) {
                if (classFilter.match(currentClass)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("collect:" + currentClass);
                    }
                    matchedClasses.add(currentClass);
                }
            }
        }
        return matchedClasses;
    }


    @Override
    public Object getObject() throws Exception {
        return findClasses();
    }


    @Override
    public Class<?> getObjectType() {
        return List.class;
    }


    @Override
    public boolean isSingleton() {
        return true;
    }
}
